home *** CD-ROM | disk | FTP | other *** search
- package assembly pc_sound is
-
- if memory_model = 0 then
- pragma memory_model(0);
- else
- pragma memory_model(1);
- end if;
-
- CSEG
- jmp main -- jump to initialization
-
- DSEG
- prevwhistle db ?
- a_sample_duration dw ?
- on_off_bytes db 256 dup(?)
-
- CSEG
- on_off_pattern equ $
- dw 2#00000000_11111111# -- 0 nibbles are in sign+magnitude form
- dw 2#00000001_11111111# -- 1
- dw 2#00000011_11111111# -- 2
- dw 2#00000111_11111111# -- 3
- dw 2#00001111_11111111# -- 4
- dw 2#00011111_11111111# -- 5
- dw 2#00111111_11111111# -- 6
- dw 2#01111111_11111111# -- 7
- dw 2#00000000_11111110# -- -1
- dw 2#00000000_01111110# -- -2
- dw 2#00000000_00111110# -- -3
- dw 2#00000000_00011110# -- -4
- dw 2#00000000_00001110# -- -5
- dw 2#00000000_00000110# -- -6
- dw 2#00000000_00000010# -- -7
- dw 2#00000000_00000000# -- -8
-
- get_ticks: -- return current tick count in ax
- xor al,al
- pushf -- save int enable status
- cli -- lock out interrupts
- out 43h,al -- read counter 0
- jmp short gtl -- (don't go too fast)
- gtl:
- in al,40h -- get lsb of timer
- xchg ah,al --
- jmp short gth -- (don't go too fast)
- gth:
- in al,40h -- get msb of timer
- xchg ah,al --
- popf -- restore int enable status
- ret
-
- play_ax_till_dx: -- destroys ax,bx
- -- high nibble of al contains amplitude
- -- dx contains timeout value
- mov bx,on_off_bytes
- add bx,ax
- xchg si,bx
- even
- pbd_loop: -- output 16 speaker on/off bytes, then,
- push dx -- if we haven't timed out, do it again
- mov dx,61h
- lodsw
- out dx,al
- mov al,ah
- out dx,al
- lodsw
- out dx,al
- mov al,ah
- out dx,al
- lodsw
- out dx,al
- mov al,ah
- out dx,al
- lodsw
- out dx,al
- mov al,ah
- out dx,al
- lodsw
- out dx,al
- mov al,ah
- out dx,al
- lodsw
- out dx,al
- mov al,ah
- out dx,al
- lodsw
- out dx,al
- mov al,ah
- out dx,al
- lodsw
- out dx,al
- xor al,al
- pushf -- save int enable status
- cli -- lock out interrupts
- out 43h,al -- read counter 0
- mov al,ah
- out dx,al
- in al,40h -- get lsb of timer
- xchg ah,al --
- sub si,16
- in al,40h -- get msb of timer
- xchg ah,al --
- popf -- restore int enable status
- pop dx
- cmp ax,dx
- jns pbd_loop
- xchg si,bx
- ret
-
- play_it_out:
- -- ds:si => sound block
- -- cx => N of bytes in sound block
- -- destroys ax,bx,dx and si,cx
- call get_ticks
- mov dx,ax
- cld
- play_it_out_loop:
- mov al,es:[si]
- and ax,16#00F0#;
- sub dx,[a_sample_duration]
- call play_ax_till_dx
- mov al,es:[si]
- inc si
- and ax,16#000F#
- shl al,1
- shl al,1
- shl al,1
- shl al,1
- sub dx,[a_sample_duration]
- call play_ax_till_dx
- loop play_it_out_loop
- mov al,[prevwhistle]
- out 61h,al
- ret
-
- procedure set_sample_rate(samples_per_second:in sample_rates) is
- pop ax -- save ret address
- if memory_model = 1 then
- pop dx
- end if;
- pop cx -- cx:=sound_length
- if memory_model = 1 then -- restore ret address
- push dx
- end if;
- push ax
- mov ax,13532 -- dx:ax := 1193180
- mov dx,18
- div cx
- mov [a_sample_duration],ax
- if memory_model = 0 then
- ret
- else
- ret far
- end if;
- end set_sample_rate;
-
- procedure playback(sound:in system.address;sound_length:in natural) is
- -- clobbers ax,bx,cx,dx,si
- pop ax -- save ret address
- if memory_model = 1 then
- pop dx
- end if;
- pop cx -- cx:=sound_length
- pop si -- si:=sound(sound'first)'address
- mov bx,es
- les si,lword ptr[si]
- if memory_model = 1 then -- restore ret address
- push dx
- end if;
- push ax
- push bx
- call play_it_out
- pop es
- if memory_model = 0 then
- ret
- else
- ret far
- end if;
- end playback;
-
- main:
- mov ax,149 -- default sample rate:=8K
- mov [a_sample_duration],ax
- in al,61h
- mov [prevwhistle],al
- and al,16#FD#
- mov bl,al -- fill on_off_bytes with 16 lists of 16
- mov di,on_off_bytes -- speaker control bytes, on and off matching
- mov cx,16 -- the bits in on_off_pattern
- cld
- mov si,on_off_pattern
- amplitude_loop:
- push cx
- seg cs
- lodsw
- mov cx,16
- bit_loop:
- mov bh,2 -- bh:=non_speaker_bits | one bit from ax
- and bh,al
- or bh,bl
- mov [di],bh
- inc di
- ror ax,1
- loop bit_loop
- pop cx
- loop amplitude_loop
- end pc_sound;